
#include <stdint.h>
#include "BitReverse.h"
#include "BitSlider.h"


void BitSlider_Init(BitSlider_T* slider, uint32_t* bundles, uint32_t num_bundles, uint32_t head){
	slider->bundles = bundles;
	slider->num_bundles = num_bundles;
	slider->head = head;
	slider->tail = head;
}

int BitSlider_Add(BitSlider_T* slider, uint8_t val){
	if(BitSlider_TailSpace(slider) == 0){
		return -1;
	}
	BitBundles_Write(slider->bundles, slider->tail, val);
	slider->tail++;
	return 0;
}

int BitSlider_Remove(BitSlider_T* slider, uint8_t* val){
	if(BitSlider_Length(slider) == 0){
		return -1;
	}
	slider->tail--;
	*val = BitBundles_Read(slider->bundles, slider->tail);
	return 0;
}

int BitSlider_Push(BitSlider_T* slider, uint8_t val){
	if(BitSlider_HeadSpace(slider) == 0){
		return -1;
	}
	slider->head--;
	BitBundles_Write(slider->bundles, slider->head, val);
	return 0;
}

int BitSlider_Pop(BitSlider_T* slider, uint8_t* val){
	if(BitSlider_Length(slider) == 0){
		return -1;
	}
	slider->head++;
	*val = BitBundles_Read(slider->bundles, slider->head);
	return 0;
}


int BitSlider_AddBits(BitSlider_T* slider, uint32_t val, uint32_t num, uint32_t off){
	if(BitSlider_TailSpace(slider) < num){
		return -1;
	}
	
	uint32_t bundle = val;
	uint32_t tail = slider->tail;
	slider->tail += num;
	return BitBundles_WriteSnap(slider->bundles, tail, bundle, num, off);
}

int BitSlider_RemoveBits(BitSlider_T* slider, uint32_t* val, uint32_t num, uint32_t off){
	if(BitSlider_Length(slider) < num){
		return -1;
	}
	
	slider->tail -= num;
	return BitBundles_ReadSnap(slider->bundles, slider->tail, val, num, off);
}


int BitSlider_PushBits(BitSlider_T* slider, uint32_t val, uint32_t num, uint32_t off){
	if(BitSlider_TailSpace(slider) < num){
		return -1;
	}

	slider->head -= num;
	return BitBundles_WriteSnap(slider->bundles, slider->head , val, num, off);
}

int BitSlider_PopBits(BitSlider_T* slider, uint32_t* val, uint32_t num, uint32_t off){
	if(BitSlider_Length(slider) < num){
		return -1;
	}
	
	uint32_t head = slider->head;
	slider->head += num;
	return BitBundles_ReadSnap(slider->bundles, head, val, num, off);
}


int BitSlider_AddLSB8(BitSlider_T* slider, uint8_t val){
	if(BitSlider_TailSpace(slider) < 8){
		return -1;
	}
	
	uint32_t bundle = val;
	uint32_t tail = slider->tail;
	slider->tail += 8;
	return BitBundles_WriteSnap(slider->bundles, tail, bundle, 8, 0);
}

#if 0
int BitSlider_AddLSB8(BitSlider_T* slider, uint8_t val){
	int ret;
	uint32_t i;
	
	for(i = 0; i < 8; i++){
		ret = BitSlider_Add(slider, Bit(val, i));
		if(ret){
			break;
		}
	}
	
	return i;
}
#endif 

int BitSlider_AddMSB8(BitSlider_T* slider, uint8_t val){
	return BitSlider_AddLSB8(slider, BitReverse8(val));
}

#if 0
int BitSlider_AddMSB8(BitSlider_T* slider, uint8_t val){
	int ret;
	uint32_t i;
	
	for(i = 8; i > 0; ){
		i--;
		ret = BitSlider_Add(slider, Bit(val, i));
		if(ret){
			break;
		}
	}
	
	return 8 - i;
}
#endif 

int BitSlider_RemoveLSB8(BitSlider_T* slider, uint8_t* val){

	if(BitSlider_Length(slider) < 8){
		return -1;
	}
	
	slider->tail -= 8;
	uint32_t snap = 0;
	BitBundles_ReadSnap(slider->bundles, slider->tail, &snap, 8, 0);
	*val = snap;
	
	return 8;
}


#if 0
int BitSlider_RemoveLSB8(BitSlider_T* slider, uint8_t* val){
	int ret; 
	uint32_t i;
	uint8_t bit;
	uint8_t v = 0;
	
	for(i = 0; i < 8; i++){
		uint8_t bit;
		ret = BitSlider_Remove(slider, &bit);
		if(ret){
			break;
		}
		v |= bit << i;
	}
	
	*val = v;
	
	return i;
}
#endif 

int BitSlider_RemoveMSB8(BitSlider_T* slider, uint8_t* val){
	int ret = BitSlider_RemoveLSB8(slider, val);

	if(ret == 8){
		*val = BitReverse8(*val);
	}
	
	return ret;
}

#if 0
int BitSlider_RemoveMSB8(BitSlider_T* slider, uint8_t* val){
	int ret; 
	uint32_t i;
	uint8_t bit;
	uint8_t v = 0;
	
	for(i = 8; i > 0; ){
		uint8_t bit;
		ret = BitSlider_Remove(slider, &bit);
		if(ret){
			break;
		}
		i--;
		v |= bit << i;
	}
	
	*val = v;
	
	return i;
}
#endif 

int BitSlider_PushLSB8(BitSlider_T* slider, uint8_t val){
	if(BitSlider_HeadSpace(slider) < 8){
		return -1;
	}
	
	slider->head -= 8;
	return BitBundles_WriteSnap(slider->bundles, slider->head , val, 8, 0);
}

int BitSlider_PushMSB8(BitSlider_T* slider, uint8_t val){
	return BitSlider_PushLSB8(slider, BitReverse8(val));
}

#if 0
int BitSlider_PushLSB8(BitSlider_T* slider, uint8_t val){
	int ret;
	uint32_t i;
	
	for(i = 0; i < 8; i++){
		ret = BitSlider_Push(slider, Bit(val, i));
		if(ret){
			break;
		}
	}
	
	return i;
}

int BitSlider_PushMSB8(BitSlider_T* slider, uint8_t val){
	int ret;
	uint32_t i;
	
	for(i = 8; i > 0; ){
		i--;
		ret = BitSlider_Push(slider, Bit(val, i));
		if(ret){
			break;
		}
	}
	
	return 8 - i;
}
#endif 

int BitSlider_PopLSB8(BitSlider_T* slider, uint8_t* val){
	if(BitSlider_Length(slider) < 8){
		return -1;
	}
	
	uint32_t head = slider->head;
	slider->head += 8;
	uint32_t snap = 0;
	BitBundles_ReadSnap(slider->bundles, head, &snap, 8, 0);
	*val = snap;
	
	return 8;
}

int BitSlider_PopMSB8(BitSlider_T* slider, uint8_t* val){
	int ret = BitSlider_PopLSB8(slider, val);
	if(ret == 8){
		*val = BitReverse8(*val);
	}
	
	return ret;
}

#if 0
int BitSlider_PopLSB8(BitSlider_T* slider, uint8_t* val){
	int ret; 
	uint32_t i;
	uint8_t bit;
	uint8_t v = 0;
	
	for(i = 0; i < 8; i++){
		uint8_t bit;
		ret = BitSlider_Pop(slider, &bit);
		if(ret){
			break;
		}
		v |= bit << i;
	}
	
	*val = v;
	
	return i;
}

int BitSlider_PopMSB8(BitSlider_T* slider, uint8_t* val){
	int ret; 
	uint32_t i;
	uint8_t bit;
	uint8_t v = 0;
	
	for(i = 8; i > 0; ){
		uint8_t bit;
		ret = BitSlider_Pop(slider, &bit);
		if(ret){
			break;
		}
		i--;
		v |= bit << i;
	}
	
	*val = v;
	
	return i;
}
#endif 



